package com.example.httplibrary.https

import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.os.Environment
import android.webkit.MimeTypeMap
import com.example.httplibrary.beans.ApiError
import com.example.httplibrary.beans.FileDownloadState
import com.example.httplibrary.beans.NetworkResult
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.Response
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.Locale
import javax.net.ssl.SSLHandshakeException

/**
 * @author 郑
 * @date 2025/8/4.
 * qq：331758871
 * phone：18979397268
 */
// NetworkUtils.kt
object NetworkUtils {

    // 处理网络请求结果
    suspend fun <T> safeApiCall(
        apiCall: suspend () -> Response<T>
    ): NetworkResult<T> {
        return withContext(Dispatchers.IO) {
            try {
                val response = apiCall()
                if (response.isSuccessful) {
                    response.body()?.let {
                        NetworkResult.Success(it)
                    } ?: run {
                        NetworkResult.Error(204, "Empty response body")
                    }
                } else {
                    val errorBody = response.errorBody()?.string()
                    val errorMessage = parseError(errorBody) ?: "Unknown error"
                    NetworkResult.Error(response.code(), errorMessage)
                }
            } catch (e: Exception) {
                NetworkResult.Error(
                    code = getErrorCode(e),
                    message = getNetworkErrorMessage(e)
                )
            }
        }
    }

    /**
     * 带回调的网络请求处理函数
     * @param apiCall 网络请求调用
     * @param onSuccess 成功回调
     * @param onError 失败回调
     */
    suspend fun <T> safeApiCallWithCallbacks(
        apiCall: suspend () -> Response<T>,
        onSuccess: (T) -> Unit,
        onError: (Int, String) -> Unit
    ) {
        val result = safeApiCall(apiCall)
        when (result) {
            is NetworkResult.Success -> {
                onSuccess(result.data)
            }

            is NetworkResult.Error -> {
                onError(result.code, result.message)
            }

            is NetworkResult.Loading -> {
                // 可根据需要处理 Loading 状态
            }
        }
    }


    /**
     * 带回调的网络请求处理函数（简化版）
     * @param apiCall 网络请求调用
     * @param onComplete 完成回调（无论成功或失败都会调用）
     */
    suspend fun <T> safeApiCallWithComplete(
        apiCall: suspend () -> Response<T>,
        onSuccess: (T) -> Unit,
        onError: (Int, String) -> Unit,
        onComplete: () -> Unit = {}
    ) {
        val result = safeApiCall(apiCall)
        when (result) {
            is NetworkResult.Success -> {
                try {
                    onSuccess(result.data)
                } finally {
                    onComplete()
                }
            }

            is NetworkResult.Error -> {
                try {
                    onError(result.code, result.message)
                } finally {
                    onComplete()
                }
            }

            is NetworkResult.Loading -> {
                // 忽略或处理 Loading 状态
            }
        }
    }


    // 解析错误消息
    private fun parseError(errorBody: String?): String? {
        return try {
            if (errorBody.isNullOrEmpty()) return null
            val type = object : TypeToken<ApiError>() {}.type
            Gson().fromJson<ApiError>(errorBody, type)?.message
        } catch (e: JsonSyntaxException) {
            errorBody
        } catch (e: Exception) {
            "Parse error: ${e.localizedMessage}"
        }
    }

    // 获取错误码
    private fun getErrorCode(e: Exception): Int {
        return when (e) {
            is SocketTimeoutException -> 408
            is ConnectException -> 503
            is UnknownHostException -> 404
            is SSLHandshakeException -> 426 // Upgrade Required
            is IOException -> 500
            else -> 500
        }
    }

    // 获取网络错误消息
    private fun getNetworkErrorMessage(e: Exception): String {
        return when (e) {
            is SocketTimeoutException -> "连接超时，请稍后重试"
            is ConnectException -> "无法连接到服务器，请检查网络"
            is UnknownHostException -> "无法解析主机地址"
            is SSLHandshakeException -> "安全证书验证失败"
            is IOException -> "网络IO异常: ${e.localizedMessage}"
            else -> "网络请求失败: ${e.localizedMessage ?: e.javaClass.simpleName}"
        }
    }

    // 上传文件
    fun createMultipartBodyPart(
        context: Context,
        fileUri: Uri,
        partName: String = "file"
    ): MultipartBody.Part? {
        return try {
            val fileName = getFileName(context, fileUri) ?: "unknown_file"
            val mimeType = getMimeType(context, fileUri) ?: "application/octet-stream"

            val inputStream = context.contentResolver.openInputStream(fileUri) ?: return null
            val fileBody = inputStream.use { stream ->
                stream.readBytes().toRequestBody(mimeType.toMediaTypeOrNull())
            }

            MultipartBody.Part.createFormData(partName, fileName, fileBody)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

    // 新增辅助函数：获取文件名
    private fun getFileName(context: Context, uri: Uri): String? {
        var fileName: String? = null
        when (uri.scheme) {
            ContentResolver.SCHEME_CONTENT -> {
                context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
                    val nameIndex = cursor.getColumnIndex("_display_name")
                    if (nameIndex != -1 && cursor.moveToFirst()) {
                        fileName = cursor.getString(nameIndex)
                    }
                }
            }

            ContentResolver.SCHEME_FILE -> {
                fileName = uri.lastPathSegment
            }
        }
        return fileName
    }

    // 下载文件
    suspend fun downloadFile(
        context: Context,
        fileUrl: String,
        fileName: String,
        downloadState: MutableStateFlow<FileDownloadState>
    ): File? {
        downloadState.value = FileDownloadState.Loading

        return try {
            val apiService = RetrofitClient.createService(FileDownloadApi::class.java)
            val response = apiService.downloadFile(fileUrl)

            if (response.isSuccessful) {
                response.body()?.let { body ->
                    // 创建目标文件
                    val downloadDir =
                        File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "MyApp")
                    if (!downloadDir.exists()) downloadDir.mkdirs()

                    val file = File(downloadDir, fileName)

                    // 写入文件
                    body.byteStream().use { inputStream ->
                        FileOutputStream(file).use { outputStream ->
                            val totalBytes = body.contentLength()
                            var downloadedBytes = 0L
                            val buffer = ByteArray(8192)
                            var bytesRead: Int

                            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                                outputStream.write(buffer, 0, bytesRead)
                                downloadedBytes += bytesRead

                                // 更新进度（避免除零错误）
                                if (totalBytes > 0) {
                                    val progress = (downloadedBytes * 100 / totalBytes).toInt()
                                    downloadState.value = FileDownloadState.Progress(progress)
                                }
                            }

                            downloadState.value = FileDownloadState.Success(file)
                            file
                        }
                    }
                } ?: run {
                    downloadState.value = FileDownloadState.Error("下载文件失败：空响应")
                    null
                }
            } else {
                downloadState.value = FileDownloadState.Error("下载失败：${response.code()}")
                null
            }
        } catch (e: Exception) {
            downloadState.value = FileDownloadState.Error("下载失败：${e.localizedMessage}")
            null
        }
    }

    // 获取文件的 MIME 类型
    private fun getMimeType(context: Context, uri: Uri): String? {
        return if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
            context.contentResolver.getType(uri)
        } else {
            val extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString())
            MimeTypeMap.getSingleton()
                .getMimeTypeFromExtension(extension.lowercase(Locale.getDefault()))
        }
    }
}

// 专门用于文件下载的API接口
interface FileDownloadApi {
    @retrofit2.http.GET
    @retrofit2.http.Streaming
    suspend fun downloadFile(@retrofit2.http.Url fileUrl: String): Response<okhttp3.ResponseBody>
}
